/*
 * Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Codename One designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *  
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 * 
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 * 
 * Please contact Codename One through http://www.codenameone.com/ if you 
 * need additional information or have any questions.
 */
package com.codename1.designer;

import com.codename1.ui.Display;
import com.codename1.ui.EncodedImage;
import com.codename1.ui.util.EditableResources;
import java.awt.Component;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.ListCellRenderer;
import javax.swing.SwingUtilities;

/**
 *
 * @author Shai Almog
 */
public class Import9Patch extends javax.swing.JDialog {
    private EditableResources res;
    private String theme;
    
    /** Creates new form Import9Patch */
    public Import9Patch(java.awt.Component parent, EditableResources res, String theme) {
        super((java.awt.Frame)SwingUtilities.windowForComponent(parent), true);
        this.res = res;
        this.theme = theme;
        initComponents();
        AddThemeEntry.initUIIDComboBox(uiidCombo);
        
        pack();
        setLocationByPlatform(true);
        setVisible(true);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        imageDirectory = new javax.swing.JTextField();
        pickDirectory = new javax.swing.JButton();
        jLabel3 = new javax.swing.JLabel();
        uiidCombo = new javax.swing.JComboBox();
        jLabel4 = new javax.swing.JLabel();
        styleState = new javax.swing.JComboBox();
        jPanel1 = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        okButton = new javax.swing.JButton();
        cancelButton = new javax.swing.JButton();
        jLabel5 = new javax.swing.JLabel();
        imagesCombo = new javax.swing.JComboBox();

        FormListener formListener = new FormListener();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Import 9-Patch Files");

        jLabel1.setText("<html>Select the directory where the 9-patch images are stored based on the directory hierarchy<br/>convention used in the Android platform");
        jLabel1.setName("jLabel1"); // NOI18N

        jLabel2.setText("Image Directory");
        jLabel2.setName("jLabel2"); // NOI18N

        imageDirectory.setName("imageDirectory"); // NOI18N

        pickDirectory.setText("...");
        pickDirectory.setName("pickDirectory"); // NOI18N
        pickDirectory.addActionListener(formListener);

        jLabel3.setText("Apply To");
        jLabel3.setName("jLabel3"); // NOI18N

        uiidCombo.setEditable(true);
        uiidCombo.setName("uiidCombo"); // NOI18N

        jLabel4.setText("State");
        jLabel4.setName("jLabel4"); // NOI18N

        styleState.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Unselected", "Selected", "Pressed", "Disabled" }));
        styleState.setName("styleState"); // NOI18N

        jPanel1.setName("jPanel1"); // NOI18N

        jPanel2.setName("jPanel2"); // NOI18N
        jPanel2.setLayout(new java.awt.GridLayout(1, 2));

        okButton.setText("Apply");
        okButton.setName("okButton"); // NOI18N
        okButton.addActionListener(formListener);
        jPanel2.add(okButton);

        cancelButton.setText("Close");
        cancelButton.setName("cancelButton"); // NOI18N
        cancelButton.addActionListener(formListener);
        jPanel2.add(cancelButton);

        jPanel1.add(jPanel2);

        jLabel5.setText("Image");
        jLabel5.setName("jLabel5"); // NOI18N

        imagesCombo.setName("imagesCombo"); // NOI18N

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jLabel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(jLabel2)
                            .add(jLabel3)
                            .add(jLabel4))
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, imagesCombo, 0, 390, Short.MAX_VALUE)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, imageDirectory, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 390, Short.MAX_VALUE)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, styleState, 0, 390, Short.MAX_VALUE)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, uiidCombo, 0, 390, Short.MAX_VALUE))
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(pickDirectory))))
            .add(layout.createSequentialGroup()
                .add(224, 224, 224)
                .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(210, Short.MAX_VALUE))
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(jLabel5)
                .addContainerGap(546, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(11, 11, 11)
                .add(jLabel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(jLabel2)
                    .add(imageDirectory, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(pickDirectory))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(jLabel5)
                    .add(imagesCombo, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(uiidCombo, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(jLabel3))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(styleState, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(jLabel4))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 8, Short.MAX_VALUE)
                .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .add(9, 9, 9))
        );

        pack();
    }

    // Code for dispatching events from components to event handlers.

    private class FormListener implements java.awt.event.ActionListener {
        FormListener() {}
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            if (evt.getSource() == pickDirectory) {
                Import9Patch.this.pickDirectoryActionPerformed(evt);
            }
            else if (evt.getSource() == okButton) {
                Import9Patch.this.okButtonActionPerformed(evt);
            }
            else if (evt.getSource() == cancelButton) {
                Import9Patch.this.cancelButtonActionPerformed(evt);
            }
        }
    }// </editor-fold>//GEN-END:initComponents

private void pickDirectoryActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pickDirectoryActionPerformed
        File[] result = ResourceEditorView.showOpenFileChooserWithTitle("Select The Directory", true, "Directory");
        if(result != null && result.length == 1) {
            imageDirectory.setText(result[0].getAbsolutePath());
        }
        
        File drawableHdpi = new File(imageDirectory.getText() + File.separator + "drawable-hdpi");
        File[] potentials = drawableHdpi.listFiles(new FileFilter() {
                @Override
                public boolean accept(File file) {
                    return file.getName().endsWith(".9.png");
                }
            });

        if(potentials == null || potentials.length == 0) {
            JOptionPane.showMessageDialog(this, "Can't find 9-patch files in the hdpi directory", "Error", JOptionPane.ERROR_MESSAGE);
            return;
        }

        imagesCombo.setRenderer(new DefaultListCellRenderer() {

            @Override
            public Component getListCellRendererComponent(JList jlist, Object o, int i, boolean bln, boolean bln1) {
                if(o instanceof File) {
                    o = ((File)o).getName();
                }
                return super.getListCellRendererComponent(jlist, o, i, bln, bln1);
            }
        });
        imagesCombo.setModel(new DefaultComboBoxModel(potentials));        
}//GEN-LAST:event_pickDirectoryActionPerformed

private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
    dispose();
}//GEN-LAST:event_cancelButtonActionPerformed

private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
        try {
            File[] dirs = new File(imageDirectory.getText()).listFiles(new FileFilter() {
                    @Override
                    public boolean accept(File file) {
                        return file.isDirectory();
                    }
                });
            if(dirs.length == 0) {
                JOptionPane.showMessageDialog(this, "No directories found", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }
            File drawableHdpi = new File(imageDirectory.getText() + File.separator + "drawable-hdpi");
            File drawableLdpi = new File(imageDirectory.getText() + File.separator + "drawable-ldpi");
            File drawableMdpi = new File(imageDirectory.getText() + File.separator + "drawable-mdpi");
            File drawableXHdpi = new File(imageDirectory.getText() + File.separator + "drawable-xhdpi");
            
            if(!drawableHdpi.exists()) {
                JOptionPane.showMessageDialog(this, "Can't find the drawable-hdpi directory", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }
            
            drawableHdpi = (File)imagesCombo.getSelectedItem();
            drawableLdpi = new File(drawableLdpi, drawableHdpi.getName());
            drawableMdpi = new File(drawableMdpi, drawableHdpi.getName());
            drawableXHdpi = new File(drawableXHdpi, drawableHdpi.getName());
            
            List<BufferedImage> images = new ArrayList<BufferedImage>();
            List<Integer> densities = new ArrayList<Integer>();
            BufferedImage hdpi = ImageIO.read(drawableHdpi);
            
            images.add(hdpi);
            densities.add(Display.DENSITY_HIGH);
            
            BufferedImage ldpi = null;
            if(drawableLdpi.exists()) {
                ldpi = ImageIO.read(drawableLdpi);
                images.add(ldpi);
                densities.add(Display.DENSITY_LOW);
            }
            BufferedImage mdpi = null;
            if(drawableMdpi.exists()) {
                mdpi = ImageIO.read(drawableMdpi);
                images.add(mdpi);
                densities.add(Display.DENSITY_MEDIUM);
            }
            BufferedImage xhdpi = null;
            if(drawableXHdpi.exists()) {
                xhdpi = ImageIO.read(drawableXHdpi);
                images.add(xhdpi);
                densities.add(Display.DENSITY_VERY_HIGH);
            }
            
            create9Patch(images, densities);
        } catch (IOException ex) {
            ex.printStackTrace();
            JOptionPane.showMessageDialog(this, "IO Error reading file", "Error", JOptionPane.ERROR_MESSAGE);
        }
}//GEN-LAST:event_okButtonActionPerformed


private void create9Patch(List<BufferedImage> biList, List<Integer> densities) {
    List<com.codename1.ui.EncodedImage> topLeftCodenameOne = new ArrayList<EncodedImage>();
    List<com.codename1.ui.EncodedImage> topRightCodenameOne = new ArrayList<EncodedImage>();
    List<com.codename1.ui.EncodedImage> bottomLeftCodenameOne = new ArrayList<EncodedImage>();
    List<com.codename1.ui.EncodedImage> bottomRightCodenameOne = new ArrayList<EncodedImage>();
    List<com.codename1.ui.EncodedImage> centerCodenameOne = new ArrayList<EncodedImage>();
    List<com.codename1.ui.EncodedImage> topImageCodenameOne = new ArrayList<EncodedImage>();
    List<com.codename1.ui.EncodedImage> bottomImageCodenameOne = new ArrayList<EncodedImage>();
    List<com.codename1.ui.EncodedImage> leftImageCodenameOne = new ArrayList<EncodedImage>();
    List<com.codename1.ui.EncodedImage> rightImageCodenameOne = new ArrayList<EncodedImage>();
    for(BufferedImage bi : biList) {
        int left = 0;
        for(int x = 0 ; x < bi.getWidth() ; x++) {
            int pixel = bi.getRGB(x, 0);
            if((pixel & 0xff000000) == 0xff000000) {
                break;
            }
            left++;
        }

        int right = 0;
        for(int x = bi.getWidth() - 1 ; x > 0 ; x--) {
            int pixel = bi.getRGB(x, 0);
            if((pixel & 0xff000000) == 0xff000000) {
                break;
            }
            right++;
        }

        int top = 0;
        for(int y = 0 ; y < bi.getHeight() ; y++) {
            int pixel = bi.getRGB(0, y);
            if((pixel & 0xff000000) == 0xff000000) {
                break;
            }
            top++;
        }


        int bottom = 0;
        for(int y = bi.getHeight() - 1 ; y > 0 ; y--) {
            int pixel = bi.getRGB(0, y);
            if((pixel & 0xff000000) == 0xff000000) {
                break;
            }
            bottom++;
        }

        bi = bi.getSubimage(1, 1, bi.getWidth() - 2, bi.getHeight() - 2);
        top--;
        bottom--;
        left--;
        right--;
        BufferedImage topLeft = bi.getSubimage(0, 0, left, top);
        BufferedImage topRight = bi.getSubimage(bi.getWidth() - right, 0, right, top);
        BufferedImage bottomLeft = bi.getSubimage(0, bi.getHeight() - bottom, left, bottom);
        BufferedImage bottomRight = bi.getSubimage(bi.getWidth() - right, bi.getHeight() - bottom, right, bottom);
        BufferedImage center = bi.getSubimage(left, top, bi.getWidth() - right - left, bi.getHeight() - bottom - top);
        BufferedImage topImage = bi.getSubimage(left, 0, bi.getWidth() - left - right, top);
        BufferedImage bottomImage = bi.getSubimage(left, bi.getHeight() - bottom, bi.getWidth() - left - right, bottom);
        BufferedImage leftImage = bi.getSubimage(0, top, left, bi.getHeight() - top - bottom);
        BufferedImage rightImage = bi.getSubimage(bi.getWidth() - right, top, right, bi.getHeight() - top - bottom);

        topLeftCodenameOne.add(com.codename1.ui.EncodedImage.create(ImageBorderCuttingWizard.toPng(topLeft)));
        topRightCodenameOne.add(com.codename1.ui.EncodedImage.create(ImageBorderCuttingWizard.toPng(topRight)));
        bottomLeftCodenameOne.add(com.codename1.ui.EncodedImage.create(ImageBorderCuttingWizard.toPng(bottomLeft)));
        bottomRightCodenameOne.add(com.codename1.ui.EncodedImage.create(ImageBorderCuttingWizard.toPng(bottomRight)));
        centerCodenameOne.add(com.codename1.ui.EncodedImage.create(ImageBorderCuttingWizard.toPng(center)));
        topImageCodenameOne.add(com.codename1.ui.EncodedImage.create(ImageBorderCuttingWizard.toPng(topImage)));
        bottomImageCodenameOne.add(com.codename1.ui.EncodedImage.create(ImageBorderCuttingWizard.toPng(bottomImage)));
        leftImageCodenameOne.add(com.codename1.ui.EncodedImage.create(ImageBorderCuttingWizard.toPng(leftImage)));
        rightImageCodenameOne.add(com.codename1.ui.EncodedImage.create(ImageBorderCuttingWizard.toPng(rightImage)));
    }

    String prefix = (String)uiidCombo.getSelectedItem() + ".";
    switch(styleState.getSelectedIndex()) {
        case 1:
            prefix += "sel#";
            break;
        case 2:
            prefix += "press#";
            break;
        case 3:
            prefix += "dis#";
            break;
    }
    
    com.codename1.ui.EncodedImage topLeftCodenameOneE = storeImage(topLeftCodenameOne, densities, prefix + " ");
    com.codename1.ui.EncodedImage topRightCodenameOneE = storeImage(topRightCodenameOne, densities, prefix + " ");
    com.codename1.ui.EncodedImage bottomLeftCodenameOneE = storeImage(bottomLeftCodenameOne, densities, prefix + " ");
    com.codename1.ui.EncodedImage bottomRightCodenameOneE = storeImage(bottomRightCodenameOne, densities, prefix + " ");
    com.codename1.ui.EncodedImage centerCodenameOneE = storeImage(centerCodenameOne, densities, prefix + " ");
    com.codename1.ui.EncodedImage topImageCodenameOneE = storeImage(topImageCodenameOne, densities, prefix + " ");
    com.codename1.ui.EncodedImage bottomImageCodenameOneE = storeImage(bottomImageCodenameOne, densities, prefix + " ");
    com.codename1.ui.EncodedImage leftImageCodenameOneE = storeImage(leftImageCodenameOne, densities, prefix + " ");
    com.codename1.ui.EncodedImage rightImageCodenameOneE = storeImage(rightImageCodenameOne, densities, prefix + " ");
    
    
    com.codename1.ui.plaf.Border b = com.codename1.ui.plaf.Border.createImageScaledBorder(topImageCodenameOneE, 
            bottomImageCodenameOneE, leftImageCodenameOneE,
            rightImageCodenameOneE, topLeftCodenameOneE, topRightCodenameOneE,
            bottomLeftCodenameOneE, bottomRightCodenameOneE, centerCodenameOneE);
    
    Hashtable newTheme = new Hashtable(res.getTheme(theme));
    newTheme.put(prefix + "border", b);
    res.setTheme(theme, newTheme);
}

    private com.codename1.ui.EncodedImage storeImage(List<com.codename1.ui.EncodedImage> imgs, List<Integer> densities, String prefix) {
        int i = 1;
        while(res.containsResource(prefix + "_" + i + ".png")) {
            i++;
        }
        EditableResources.MultiImage multi = new EditableResources.MultiImage();
        int[] dpis = new int[densities.size()];
        com.codename1.ui.EncodedImage[] images = new com.codename1.ui.EncodedImage[dpis.length];
        for(int iter = 0 ; iter < dpis.length ; iter++) {
            dpis[iter] = densities.get(iter);
            images[iter] = imgs.get(iter);
        }
        
        multi.setDpi(dpis);
        multi.setInternalImages(images);
        res.setMultiImage(prefix + "_" + i + ".png", multi);
        return multi.getBest();        
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton cancelButton;
    private javax.swing.JTextField imageDirectory;
    private javax.swing.JComboBox imagesCombo;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JButton okButton;
    private javax.swing.JButton pickDirectory;
    private javax.swing.JComboBox styleState;
    private javax.swing.JComboBox uiidCombo;
    // End of variables declaration//GEN-END:variables
}
